<template>
  <div class="bf-form-parse">
    <n-tabs
      type="line"
      animated
      v-if="templates.tabs && templates.tabs.length > 0"
      v-model:value="state.selectTabKey"
    >
      <n-tab-pane :name="item.key" :tab="item.title" v-for="item in templates.tabs" :key="item.key" />
    </n-tabs>
    <n-form ref="formRef" :model="props.value">
      <n-grid>
        <n-gi v-for="item in templates.template" :key="item.keyPath" :span="item.span" :offset="item.offset">
          <n-form-item
            :label="item.label"
            v-if="item.type === 'text'"
            v-show="item.tabKey == state.selectTabKey"
            :label-align="item.labelAlign"
            :label-placement="item.labelPlacement"
            :label-width="item.labelWidth"
          >
            <n-input v-model:value="state.formData[item.keyPath!]" v-bind="item.textProps" />
          </n-form-item>
          <n-form-item
            :label="item.label"
            v-else-if="item.type === 'textarea'"
            v-show="item.tabKey == state.selectTabKey"
            :label-align="item.labelAlign"
            :label-placement="item.labelPlacement"
            :label-width="item.labelWidth"
          >
            <n-input
              v-model:value="state.formData[item.keyPath!]"
              v-bind="item.textareaProps"
              type="textarea"
            />
          </n-form-item>
          <n-form-item
            :label="item.label"
            v-else-if="item.type === 'number'"
            v-show="item.tabKey == state.selectTabKey"
            :label-align="item.labelAlign"
            :label-placement="item.labelPlacement"
            :label-width="item.labelWidth"
          >
            <n-input-number v-model:value="state.formData[item.keyPath!]" v-bind="item.numberProps" />
          </n-form-item>
          <n-form-item
            :label="item.label"
            v-else-if="item.type === 'select'"
            v-show="item.tabKey == state.selectTabKey"
            :label-align="item.labelAlign"
            :label-placement="item.labelPlacement"
            :label-width="item.labelWidth"
          >
            <n-select v-model:value="state.formData[item.keyPath!]" v-bind="item.selectProps" />
          </n-form-item>
          <n-form-item
            :label="item.label"
            v-else-if="item.type === 'timePicker'"
            v-show="item.tabKey == state.selectTabKey"
            :label-align="item.labelAlign"
            :label-placement="item.labelPlacement"
            :label-width="item.labelWidth"
          >
            <n-time-picker v-model:value="state.formData[item.keyPath!]" v-bind="item.timePickerProps" />
          </n-form-item>
          <n-form-item
            :label="item.label"
            v-else-if="item.type === 'datePicker'"
            v-show="item.tabKey == state.selectTabKey"
            :label-align="item.labelAlign"
            :label-placement="item.labelPlacement"
            :label-width="item.labelWidth"
          >
            <n-date-picker v-model:value="state.formData[item.keyPath!]" v-bind="item.datePickerProps" />
          </n-form-item>
          <n-form-item
            :label="item.label"
            v-else-if="item.type === 'transfer'"
            v-show="item.tabKey == state.selectTabKey"
            :label-align="item.labelAlign"
            :label-placement="item.labelPlacement"
            :label-width="item.labelWidth"
          >
            <n-transfer v-model:value="state.formData[item.keyPath!]" v-bind="item.transferProps" />
          </n-form-item>
          <n-form-item
            :label="item.label"
            v-else-if="item.type === 'radio'"
            v-show="item.tabKey == state.selectTabKey"
            :label-align="item.labelAlign"
            :label-placement="item.labelPlacement"
            :label-width="item.labelWidth"
          >
            <n-radio-group v-model:value="state.formData[item.keyPath!]">
              <n-space>
                <n-radio v-for="radio in item.radioProps?.options" :key="radio.label" v-bind="radio">
                  {{ radio.label }}
                </n-radio>
              </n-space>
            </n-radio-group>
          </n-form-item>

          <!-- 树 -->
          <n-form-item
            :label="item.label"
            v-else-if="item.type === 'tree'"
            v-show="item.tabKey == state.selectTabKey"
            :label-align="item.labelAlign"
            :label-placement="item.labelPlacement"
            :label-width="item.labelWidth"
          >
            <n-tree
              block-line
              v-model:checked-keys="state.formData[item.keyPath!]"
              v-bind="item.treeProps"
              selectable
            />
          </n-form-item>

          <n-form-item
            :label="item.label"
            v-else-if="item.type === 'checkbox'"
            v-show="item.tabKey == state.selectTabKey"
            :label-align="item.labelAlign"
            :label-placement="item.labelPlacement"
            :label-width="item.labelWidth"
          >
            <n-checkbox-group v-model:value="state.formData[item.keyPath!]">
              <n-space>
                <n-checkbox
                  v-for="checkbox in item.checkboxProps?.options"
                  :key="checkbox.value"
                  v-bind="checkbox"
                >
                  {{ checkbox.label }}
                </n-checkbox>
              </n-space>
            </n-checkbox-group>
          </n-form-item>
          <n-form-item
            :label="item.label"
            v-else-if="item.type === 'upload'"
            v-show="item.tabKey == state.selectTabKey"
            :label-align="item.labelAlign"
            :label-placement="item.labelPlacement"
            :label-width="item.labelWidth"
          >
            <n-upload
              v-model:file-list="state.formData[item.keyPath!]"
              @change="handleUploadChange($event, item.keyPath!)"
              @update:file-list="updateFileList($event, item.keyPath!)"
              response-type="json"
              v-bind="item.uploadProps"
            >
              <slot :name="'upload-' + item.keyPath"> Upload </slot>
            </n-upload>
          </n-form-item>
        </n-gi>
      </n-grid>
    </n-form>
  </div>
</template>

<script setup lang="ts">
import { NForm, NFormItem, NTabs, NTabPane, NGrid, NGi } from 'naive-ui'
import { computed, onUnmounted, reactive, watch } from 'vue'
import { BFFormItem, BFTabsForm } from './bf-form.parse'
interface BFFormParseProps {
  template?: Array<BFTabsForm & BFFormItem>
  value?: Record<string, any>
}
interface BFFormParseExpose {
  getFormData(): any
}
const props = withDefaults(defineProps<BFFormParseProps>(), {
  template: () => {
    return []
  },
  value: () => ({})
})

const state = reactive({
  selectTabKey: '',
  formData: { ...props.value }
})

watch(
  () => props.value,
  () => {
    state.formData = props.value
  },
  {
    immediate: true
  }
)

const templates = computed(() => {
  const tabs: { title: string; key: string }[] = []
  const template: BFFormItem[] = []
  props.template.forEach((item) => {
    if (item.tabTitle) {
      tabs.push({ title: item.tabTitle, key: item.tabKey! })
      item.template!.forEach((temp: BFFormItem) => {
        temp.span = temp.span || 24
        temp.offset = temp.offset || 0
        temp.tabKey = item.tabKey
        temp.labelAlign = temp.labelAlign || 'left'
        temp.labelWidth = temp.labelWidth || 'auto'
        temp.labelPlacement = temp.labelPlacement || 'left'
        template.push(temp)
      })
    } else {
      item.span = item.span || 24
      item.offset = item.offset || 0
      item.tabKey = ''
      item.labelAlign = item.labelAlign || 'left'
      item.labelWidth = item.labelWidth || 'auto'
      item.labelPlacement = item.labelPlacement || 'left'
      template.push(item)
    }
  })
  return { tabs, template }
})

const init = () => {
  if (templates.value.tabs.length > 0) {
    state.selectTabKey = templates.value.tabs[0].key
  }
}
init()

const getFormData = () => {
  return state.formData
}

let uploadResponse: any = {}
const handleUploadChange = (data: any, key: string) => {
  if (data.file.status === 'finished') {
    uploadResponse[data.file.id] = data.event.currentTarget.response
    data.fileList.forEach((item: any) => {
      item.response = uploadResponse[item.id]
    })
    state.formData[key] = data.fileList
  }
}

const updateFileList = (data: any[], key: string) => {
  data.forEach((item: any) => {
    item.response = uploadResponse[item.id]
  })
  state.formData[key] = data
}

onUnmounted(() => {
  uploadResponse = null
})

defineExpose<BFFormParseExpose>({ getFormData })
// const formData = computed(() => {
//   let newVal: { [key: string]: any } = {}
//   let strNullType = ['text', 'textarea']
//   let arrNullType = ['upload', 'transfer', 'timePicker']
//   templates.value.template.forEach((item) => {
//     if (strNullType.includes(item.type)) {
//       newVal[item.keyPath] = ''
//     }
//     if (arrNullType.includes(item.type)) {
//       newVal[item.keyPath] = []
//     }
//   })
//   return newVal
// })
</script>

<style scoped lang="scss"></style>
